spring boot 2.0.3+spring cloud熔断器Hystrix 您所在的位置:网站首页 通过maven 打docker 镜像包出错add failed stat varlib spring boot 2.0.3+spring cloud熔断器Hystrix

spring boot 2.0.3+spring cloud熔断器Hystrix

2023-08-27 19:53| 来源: 网络整理| 查看: 265

分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞。某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果是整个服务的线程资源消耗殆尽。由于服务的依赖性,会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽,知道不可用,从而导致整个服务系统不可用,即雪崩效应。为了防止雪崩效应,产生了熔断器模型。

Hystrix是Netflix公司开源的一个项目,提供了熔断器功能,能阻止分布式系统中出现联动故障。Hystrix是通过隔离服务的访问点阻止联动故障的,并提供了故障解决方案,从而提高了整个分布式系统的弹性。

当服务的某个API接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该API接口正常提供服务。当该API接口处理请求的失败次数大于设定的阈值时,hystrix判定该API接口出现了故障,打开熔断器,这时请求该API接口会执行快速失败的逻辑(即fallback回退的逻辑),不执行业务逻辑,请求的线程不会处于阻塞状态。处于打开状态的熔断器,一段时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败,若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了,则关闭熔断器。这样熔断器就具有了自我修复的能力。

最开始集成的时候,发现springBoot1.5.6 和springBoot2.0.3包不兼容,导致后面一致报错,因为工作环境用的还是srpingBoot1.5.6版本,所以练习的这个是最新版本,Hystrix在1.5版本是要自己加载的,但是2.0.3版本已经包含在spring-cloud-starter-netflix-hystrix 包里面了,我是用maven仓库,工作空间都在一起,后面分离了工作空间和maven仓库,让两个版本的依赖仓库分开 ,果然之后一切顺利,这也是比较坑的地方,

先写三个项目springcloud-eureka-server 服务注册中心  springcloud-euraka-client生产者 euraka-consumer-ribbonAndfeign-hystrix 消费者调用 ,并且ribbon 和 feign负载均衡放在一个项目里

主要是euraka-consumer-ribbonAndfeign-hystrix 项目, 先贴出POM.XML的依赖

    4.0.0

    com.example.euraka     springCloudEurakaConsumer     1.0.0     jar

    springCloudEurakaConsumer     Demo project for Spring Boot

             org.springframework.boot         spring-boot-starter-parent         2.0.3.RELEASE              

             UTF-8         UTF-8     Finchley.RELEASE     

                          org.springframework.cloud             spring-cloud-starter-netflix-eureka-client                                org.springframework.cloud             spring-cloud-starter-openfeign                               org.springframework.boot             spring-boot-starter-test             test                                org.springframework.cloud             spring-cloud-starter-netflix-hystrix                                    org.springframework.boot                 spring-boot-starter-actuator                                   org.springframework.boot             spring-boot-starter-web             

                                            org.springframework.cloud                 spring-cloud-dependencies                 ${spring-cloud.version}                 pom                 import                                                                          org.springframework.boot                 spring-boot-maven-plugin                                           com.spotify                 docker-maven-plugin                           

在项目启动类加上@EnableHystrix注解,开启hystrix熔断器功能,当然我这里加的比较多,如果是springBootCloudApplicateion也可以,主要是在超时配置的时候,会有过服务重试的操作,这个操作研究了一段时间,基本上就是超时的策略,会去调用其它服务实例,再次请求服务等,详细介绍在配置文件里

@SpringBootApplication @Configuration @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients @EnableHystrix public class DemoServerApplication {

    public static void main(String[] args) {         SpringApplication.run(DemoServerApplication.class, args);     }      /*    SpringCloud重试机制配置     首先声明一点,这里的重试并不是报错以后的重试,而是负载均衡客户端发现远程请求实例不可到达后,去重试其他实例。     其实也是Ribbon+RestTemplate的重试机制,因为是SpringCloud默认方式           对于整合了Ribbon的RestTemplate,例如一个RestTemplate添加了@LoadBalanced 注解     */     @LoadBalanced     @Bean     public RestTemplate restTemplate() {         /*HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();           httpRequestFactory.setReadTimeout(3000);           httpRequestFactory.setConnectTimeout(2000);         return new RestTemplate(httpRequestFactory);*/         return new RestTemplate();     }     //feign重试机制,feign默认是通过自己包下的Retryer进行重试配置,默认是5次,优先配置文件配置的重试策略     //如果没有配置文件,下面这样设置至少也会重试两次,本实例之外的一次调用     @Bean     public Retryer feignRetryer(){        // return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5);//默认是5次         return Retryer.NEVER_RETRY; //feign取消重试     }     

然后在CustomerRibbonController里,实现Ribbon+RestTemplate 负载均衡实现 ,其实也比较简单,因为我之前测试别的原因,我写了两个方法

@RestController public class CustomerRibbonController {

    @Autowired     RestTemplate restTemplate;     @Autowired     RibbonService  ribbonService;          //这里写了一个service 层来表示业务逻辑,当然与下面worldCustomer的方式调用也是可以的,简洁一些     // hellolmc 方法调用超时之后, 调用fallbackMethod = "hiError" 方法,自动熔断或降级     @GetMapping("/hilmc")     public String hellolmc(){         return ribbonService.consumer();     }          //此方法可以正常调用,生产者并没有超时     @RequestMapping(value = "/helloCustomer",method = RequestMethod.GET)     @HystrixCommand(fallbackMethod="fallback")     public String worldCustomer(){         return restTemplate.getForObject("http://springcloud-euraka-client/world", String.class);     }          public String fallback() {         System.out.println("fallbackMethod worldCustomer");         return "fallback Customer";     }      }

@Service public class RibbonService {

    @Autowired     RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")     public String consumer() {         return restTemplate.getForObject("http://springcloud-euraka-client/hello", String.class);     }

    public String hiError() {         return "fallbackCall";     }

}

RibbonService 是因为把业务把控制层分开,第一个方法是这样调用 

在consumer()方法上加上@HystrixCommand注解。有了该注解consumer()方法就启用了Hystrix熔断器的功能,fallbackMethod为处理回退(fallback)逻辑的方法为hiError() ,没有异常,直接返回一个字符串,也可以用抛异常的方式执行,这样在日志里可以发现哪个服务出现问题,只需要在 hiError() 里加thrable 等方式,我这里为了简便就没有做,主要是不想处理复杂的逻辑,,这样方便执行快速失败,释放线程资源,项目结构是这样

 

加上配置文件,因为是ribbon 和 feign放在一起,还有重试策略配置等,

server:   port: 5080 eureka:   client:     serviceUrl:       defaultZone: http://peer1:5012/eureka/     healthcheck:       enabled: true     lease:       duration: 5   instance:     preferIpAddress: true spring:   application:     name: springCloudEurakaConsumer #使用如下配置开启,即可实现重试:再加Feign下面的ribbon配置,就是 Ribbon+RestTemplate的重试机制    #  cloud: #    loadbalancer: #      retry:  #      enabled: true #开启hystrix功能     feign:   hystrix:     enabled: true #logging: #  level: #    org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL #lease 租期时间,不定时发送心跳包消息,如果长时间未能更新租期时间,服务就为抛弃该服务实例,注册中心会当成无用服务 # 1,Ribbon+RestTemplate的重试 #对于整合了Ribbon的RestTemplate,例如一个RestTemplate添加了@LoadBalanced 注解 #在此基础上,使用如下配置,即可实现重试: #Feign的重试与Ribbon重试整合后, 只需使用Ribbon的重试配置即可,两种重试配置一样,所以下面配置至少要重试4次 ribbon:  # 同一实例最大重试次数,不包括首次调用,配置后本实例至少会执行两次   MaxAutoRetries: 1  # 重试其他实例的最大重试次数,不包括首次所选的server,配置后本实例和其它服务注册实例至少会执行两次   MaxAutoRetriesNextServer: 1  # 是否所有操作都进行重试   OkToRetryOnAllOperations: false

到这里ribbon配置基本完成,

依次启动springcloud-eureka-server 的服务注册,springcloud-euraka-client生产者 euraka-consumer-ribbonAndfeign-hystrix消费消息,在浏览器访问http://localhost:5080/hilmc,会显示如下, 因为我在生产端直接睡眠了9秒,所以触发熔断

再输入正常url   http://localhost:5080/helloCustomer 显示正常

 

在Feign上使用熔断器 下面是feign 包

Feign的起步依赖中已经引入了Hystrix的依赖,只需要在eureka-feign-client工程的配置文件中开启hystrix功能即可,前方配置文件已经给出

EurekaClientFeign 接口,

@Component @FeignClient(value = "springcloud-euraka-client",fallback = HiHystrix.class) public interface EurekaClientFeign {

    /**      * 绑定 springcloud-euraka-client 服务的 /hi/ 接口      *      * @param name      * @return      */     @GetMapping(value = "/hi")     String sayHiFromClientEureka(@RequestParam(value = "name")String name);          @GetMapping(value = "/hi2")     String sayHiFromClientEureka2(@RequestParam(value = "name")String name);      }

HiHystrix 类必须实现EurekaClientFeign接口,才能触发熔断器的fallback

@Component public class HiHystrix implements EurekaClientFeign {

    @Override     public String sayHiFromClientEureka(String name) {         return "hi,"+name+",sorry.error!";     }

    @Override     public String sayHiFromClientEureka2(String name) {           return "hi2,"+name+",sorry.error! Hi2";     } }

CustomerFeignController 类

@RestController public class CustomerFeignController {          @Autowired     EurekaClientFeign eurekaclient;     //超时调用fallback 的方法,如果禁止重试,也会调用两次,如果配置文件有调用其它实例,至少会执行3次以上     //所以在写接口的时候,需要对接口增加幂等性     @GetMapping("/hi")     public String sayHi(@RequestParam(defaultValue = "cralor",required = false)String name){         return eurekaclient.sayHiFromClientEureka(name);     }     //正常执行调用     @GetMapping("/hi2")     public String sayHi2(@RequestParam(defaultValue = "lmc",required = false)String name){         return eurekaclient.sayHiFromClientEureka2(name);     }     @Autowired     private GreetingClient greetingClient;     @RequestMapping("/get-greeting")     public String greeting(Model model) {        Map parpm= new HashMap();           parpm.put("name", "lmc");           parpm.put("test", "demo");         String message =  greetingClient.greeting(parpm.toString()); //以字符串方式传参数         return message+":传参数";     }

浏览器访问输入http://localhost:5080//hi2 正常调用

浏览器访问输入http://localhost:5080//hi

这个方法在springcloud-euraka-client 项目里启动睡眠6秒超时

 

都 能触发熔断降级处理, 说明是可行,

还要注意的是 feign 重试机制,就是在超时或者异常的情况下,会不断去重试调用,feign默认重试次数是5次,100ms一次

这最前面的配置文件最后参数有说明 ,就是除了本身实例,本身服务,再去调用其它实例和服务,在集群的环境下配置这种策略最好,如果碰上数据量过大请求过去超时,但是生产者那方会如果没有限制超时就会继续执行,这个时间再去重试请求其实是非常危险的,一条数据会碰上执行两次以上,get的数据可能影响不大,如果是post写数据就要考虑接口的幂等性

使用Hystrix Dashboard监控熔断器的状态 这个跟eurak服务注册类型的步骤,有时间再弄会,集群监控所有熔断器的状态和运用情况等

githut项目地址 https://github.com/lmchuyang/huyang

如有理解 错的,希望大家能指正交流

参考资料 https://www.cnblogs.com/cralor/p/9230728.html 

参考资料 https://www.jb51.net/article/129336.htm



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有